# 列表推导式
# 基础列表推导式


squares = [x**2 for x in range(1,6)]
print("列表推导式：", squares)    # 列表推导式： [1, 4, 9, 16, 25]
# 条件列表推导式
squares = [x**2 for x in range(1,11) if x%2==0]
print("条件列表推导式：", squares) # 条件列表推导式： [4, 16, 36, 64, 100]

print("=" * 50)
# 字典推导式
# 基本字典稚导式
square_dict = {x: x**2 for x in range(1,6)}
print("字典推导式：", square_dict)    # 字典推导式： {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 条件字典推导式
square_dict = {x: x**2 for x in range(1,11) if x%2==0}
print("条件字典推导式：", square_dict)  # 条件字典推导式： {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

print("=" * 50)
# 集合推导式
# 基本集合推导式
square_set = {x**2 for x in range(1,6)}
print("集合推导式：", square_set) # 集合推导式： {1, 4, 9, 16, 25}
# 条件集合推导式
square_set = {x**2 for x in range(1,11) if x%2==0}
print("条件集合推导式：", square_set)   # 条件集合推导式： {64, 100, 4, 36, 16}

print("=" * 50)
# 生成器表达式
# 元组推导式本质上是生成器表达式，元组是用()表示的，这和写一个值有冲突
squares_gen = (x**2 for x in range(1,6))
print("生成器表达式：", list(squares_gen)) # [1, 4, 9, 16, 25]
print("生成器表达式：", squares_gen)
# 由于我们把生成器表达式转为list了，再遍历生成器表达式，不会遍历到值了
# 有了这个生成器表达式后我们可以遍历
for i in squares_gen:
    print(i)
print("============")
# 我们也可以转换成列表
# 上面已经对生器表达式进行了遍历，所以这里再次遍历会得到空
print("生成器表达式：", list(squares_gen)) # []

print("=" * 50)
# 可迭代对象 判断
res = iter([1,2,3])
print(res)  # <list_iterator object at 0x000001B7D1898B50>
try:
    print(iter(42))
except TypeError as e:
    print(42, "不能迭代：", e)

from typing import Iterable
# 使用isinstance()判断
print(isinstance((1,2,3), Iterable))    # True

print("=" * 50)
# 手动实现迭代器
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < len(self.data):
            item = self.data[self.index]
            self.index += 1
            return item
        else:
            raise StopIteration

iterator = MyIterator([1,2,3])
for i in iterator:
    print(i,end="\t")
print()
print("=" * 50)
iter1 = MyIterator([1,2,3])
print(next(iter1))  # 1
print(next(iter1))  # 2
print(next(iter1))  # 3
# 上面三个next()调用把所有元素都取完了，所以再取的话会报错
# print(next(iter1))  # 这里会报StopIteration异常

print("=" * 50)
# 生成器
def countdown(n):
    while n > 0:
        # 这里yield一个值，而不是return一个值
        yield n
        n -= 1

gen = countdown(5)
print(gen)  # <generator object countdown at 0x00000170F96A6980>
# 生成器可以使用next()一次获取一个值
# print(next(gen))    # 5
# 生成器可以使用for循环来一次一次的获取它所有的值
for i in gen:
    print(i,end="\t")
print()
# 由于生成器中的值已经取完，所以这里再调用next()会报错
# print(next(gen))

